'''
    Module with functions for fileDriver 
'''

from authDSL.drivers import DefaultDriver
import MySQLdb
import simplexmlapi


class DatabaseAccess():
    def __init__(self):
        self.read_config_file()

    def read_config_file(self):
        with open('authDSL/drivers/SQLDriver/config.xml', 'r') as f:
            read_data = f.read()
        f.closed
        self.config = simplexmlapi.loads(read_data)
        
        if self.config is not None:
            self.address        = self.config.address._
            self.user           = self.config.user._
            self.password       = self.config.password._
            self.database_name  = self.config.database._

    def connect(self):
        self.db = MySQLdb.connect(self.address, self.user, self.password, self.database_name)
            
    def table_exists(self, table):
        query = "SELECT table_name FROM information_schema.tables WHERE table_schema = '%s' AND table_name = '%s'"%(self.database_name, table)
        
        data = self.select_one(query)
        if data is None:
            return False
        
        return True
    
    def select_one(self, query):
        cursor = self.db.cursor()
        cursor.execute(query)
        
        return cursor.fetchone()
    
    def select_all(self, query):
        cursor = self.db.cursor()
        cursor.execute(query)
        
        return cursor.fetchall()
            
    def execute(self, sql):    
        cursor = self.db.cursor()
        cursor.execute(sql)
    
    def insert(self, sql):    
        cursor = self.db.cursor()
        cursor.execute(sql)
        self.db.commit()
    
    def delete(self, sql):    
        cursor = self.db.cursor()
        cursor.execute(sql)
        self.db.commit()
    
    def disconnect(self):
        self.db.close()


class SQLDriver():
    database = DatabaseAccess()
    
    def select_one(self, query):
        return self.database.select_one(query)
    
    def select_all(self, query):
        return self.database.select_all(query)
            
    def execute(self, sql):    
        self.database.execute(sql)
    
    def insert(self, sql):    
        self.database.insert(sql)
    
    def delete(self, sql):    
        self.database.delete(sql)
    
    def disconnect(self):
        self.database.disconnect()
    
    def __init__(self):
        self.database.connect()
        if(not self.database.table_exists("user")):
            self.create_tables()
    
    def create_tables(self):
        user_table  = "CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user` varchar(255) DEFAULT NULL, `password` varchar(255) DEFAULT NULL, PRIMARY KEY (`ID`)) ENGINE=InnoDB DEFAULT CHARSET=latin1"
        group_table = "CREATE TABLE `groups` ( `id` int(11) NOT NULL AUTO_INCREMENT, `group_name` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=latin1"
        user_has_group_table = "CREATE TABLE `user_has_group` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user_id` int(11) NOT NULL, `group_id` int(11) NOT NULL, PRIMARY KEY (`id`), FOREIGN KEY (user_id)REFERENCES user(id), FOREIGN KEY (group_id) REFERENCES groups(id)) ENGINE=InnoDB DEFAULT CHARSET=latin1"
        auth_table  = "CREATE TABLE `auth` (`id` int(11) NOT NULL AUTO_INCREMENT,`user_id` int(11) NOT NULL,PRIMARY KEY (`id`),FOREIGN KEY (user_id)REFERENCES user(id)) ENGINE=InnoDB DEFAULT CHARSET=latin1" 
        
        self.database.execute(user_table)
        self.database.execute(group_table)
        self.database.execute(user_has_group_table)
        self.database.execute(auth_table)
    
    def user_exists(self, user):
        query = "SELECT * FROM user where user='%s'"%(user)
        data = self.database.select_one(query)
        if(data is None):
            return False
        return True
    
    def get_user(self, user, password=None):
        if password is not None:
            query = "SELECT * FROM user where user='%s' and password='%s'"%(user,password)
        else:
            query = "SELECT * FROM user where user='%s'"%(user)
            
        return self.database.select_one(query)
    
    def get_group(self, group):
        query = "SELECT * FROM groups where group_name='%s'"%(group)
        return self.database.select_one(query)
    
    def user_is_authenticated(self, user_id):
        query = "SELECT * FROM auth where user_id='%s'"%(user_id)
        data = self.database.select_one(query)
        if(data is None):
            return False
        return True
    
    def user_has_group(self, user_id, group_id):
        query = "SELECT * from user_has_group where user_id = '%s' and group_id='%s'"%(user_id, group_id)
        data = self.database.select_one(query)
        if data is None:
            return False
        return True
        
        
sql_driver = SQLDriver()
class Decorators(DefaultDriver.Decorators):
    
    @staticmethod
    def is_auth(func):
        def wrap(f):
            def wrapped_f(*args):
                user = args[0]
                data = sql_driver.get_user(user)
                if data is not None and sql_driver.user_is_authenticated(data[0]):
                    f(*args)
                else:
                    print "Usuario nao tem permissao para acessar metodo"
            return wrapped_f
        return wrap(func)
    
    @staticmethod
    def has_group(group):
        def wrap(f):
            def wrapped_f(*args):
                user = args[0]
                user_data = sql_driver.get_user(user)
                group_data = sql_driver.get_group(group)
                if user_data is not None and group_data is not None:
                    if sql_driver.user_has_group(user_data[0], group_data[0]): 
                        f(*args)
                    else:
                        print "Usuario nao possui grupo"
                else:
                    print "Usuario ou grupo inexistentes"
            return wrapped_f
        return wrap


    


#
# Authentication functions
#

class Authentication(DefaultDriver.Authentication):
    """
    Class that defines functions for authentication. 
    """
   
    def __init__(self):
        pass
    
    def create_user(self, user, password):
        if(not sql_driver.user_exists(user)):
            sql = "INSERT INTO user(user, password) VALUES('%s','%s')"%(user, password)
            sql_driver.insert(sql)
        else:
            print "Usuario ja existe"
    
    def authenticate(self, user, password):
        user_data = sql_driver.get_user(user, password)
        if(user_data is not None):
            if(not sql_driver.user_is_authenticated(user_data[0])):
                sql = "INSERT INTO auth(user_id) VALUES('%s')"%(user_data[0])
                sql_driver.insert(sql)
            else:
                print "Usuario ja autenticado"
            return True
        else:
            print "Usuario e senha errados"
                
        return False
    
    def logout(self, user):
        user_data = sql_driver.get_user(user)
        if(user_data is not None and sql_driver.user_is_authenticated(user_data[0])):
            sql = "DELETE FROM auth where user_id='%s'"%(user_data[0])
            sql_driver.delete(sql)
            return True
        else:
            print "Nao eh possivel dar logout"
        
        return False
    
    def add_group(self, user, group):
        user_data = sql_driver.get_user(user)
        group_data = sql_driver.get_group(group)
        if(user_data is None):
            return False
        
        if group_data is None:
            sql = "INSERT INTO groups(group_name) VALUES ('%s')"%(group)
            sql_driver.insert(sql)
            group_data = sql_driver.get_group(group)
        
        if sql_driver.user_has_group(user_data[0], group_data[0]):
            print "Usuario ja possui grupo"
            return True
        
        sql = "INSERT INTO user_has_group(user_id, group_id) VALUES ('%s','%s')"%(user_data[0], group_data[0])
        sql_driver.insert(sql)
    
        return True
    
    def remove_group(self, group):
        group_data = sql_driver.get_group(group)
        if group_data is None:
            return True
        
        delete1 = "DELETE FROM groups where id='%s'"%(group_data[0])
        delete2 = "DELETE FROM user_has_group where group_id='%s'"%(group_data[0])
        sql_driver.delete(delete2)
        sql_driver.delete(delete1)
